package cn.rainless.zxing.demo;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

public class BitMatrixUtils {
  private static final int BLACK = 0xFF000000;//用于设置图案的颜色
  private static final int WHITE = 0xFFF7F7F7; //用于背景色

  private BitMatrixUtils() {
  }

  public static BufferedImage toBufferedImage(BitMatrix matrix) {
    int width = matrix.getWidth();
    int height = matrix.getHeight();
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        image.setRGB(x, y, (matrix.get(x, y) ? BLACK : WHITE));
      }
    }
    return image;
  }

  public static BufferedImage createQrcode(String content, int width, int height, String logo) throws WriterException, IOException {
    HashMap<EncodeHintType, Object> hints = new HashMap();
    hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
    hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//纠错等级L,M,Q,H
    hints.put(EncodeHintType.MARGIN, 0); //边距
    BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
    BufferedImage matrixImage = toBufferedImage(bitMatrix);
    if (StringUtils.isNotBlank(logo)) {
      try (InputStream is = getInputStream(logo)) {
        if (is != null) {
          return setMatrixLogo(matrixImage, is);
        }
      }
    }

    return matrixImage;
  }

  public static BufferedImage readImage(String path) throws IOException {
    try (InputStream is = getInputStream(path)) {
      if (is != null) {
        return ImageIO.read(is);
      }
    }
    return null;
  }

  private static InputStream getInputStream(String path) throws IOException {
    InputStream is;
    File file = new File(path);
    if (file.exists() && file.isFile()) {
      is = new FileInputStream(file);
    } else {
      is = BitMatrixUtils.class.getResourceAsStream(path);
    }
    return is;
  }

  public static BufferedImage setMatrixLogo(BufferedImage matrixImage, InputStream logoInputStream) throws IOException {
    /**
     * 读取二维码图片，并构建绘图对象
     */
    Graphics2D graph = matrixImage.createGraphics();
    int matrixWidth = matrixImage.getWidth();
    int matrixHeight = matrixImage.getHeight();

    /**
     * 读取Logo图片
     */
    BufferedImage logo = ImageIO.read(logoInputStream);

    //开始绘制图片
    graph.drawImage(logo, matrixWidth / 5 * 2, matrixHeight / 5 * 2, matrixWidth / 5, matrixHeight / 5, null);
    //绘制边框
    BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
    // 设置笔画对象
    graph.setStroke(stroke);
    //指定弧度的圆角矩形
    RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth / 5 * 2, matrixHeight / 5 * 2, matrixWidth / 5, matrixHeight / 5, 20, 20);
    graph.setColor(Color.white);
    // 绘制圆弧矩形
    graph.draw(round);

    //设置logo 有一道灰色边框
    BasicStroke stroke2 = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
    // 设置笔画对象
    graph.setStroke(stroke2);
    RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth / 5 * 2 + 2, matrixHeight / 5 * 2 + 2, matrixWidth / 5 - 4, matrixHeight / 5 - 4, 20, 20);
    graph.setColor(new Color(222, 222, 222));
    graph.draw(round2);// 绘制圆弧矩形

    graph.dispose();
    matrixImage.flush();
    return matrixImage;
  }
}